package com.manlitech.manlichat.base.netty.initializer;

import com.manlitech.manlichat.base.netty.handler.MyBinaryWebSocketFrameHandler;
import com.manlitech.manlichat.base.netty.handler.MyWebSocketHandler;
import com.manlitech.manlichat.base.netty.handler.MyNettyExceptionHandler;
import com.manlitech.manlichat.base.netty.initializer.ssl.NettySsl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

@Component
public class NettyServerWebsocketHandlerInitializer extends ChannelInitializer<Channel> {

    private Logger logger = LoggerFactory.getLogger(getClass());


    @Autowired
    MyWebSocketHandler myWebSocketHandler;

    @Autowired
    MyBinaryWebSocketFrameHandler myBinaryWebSocketFrameHandler;

    @Autowired
    MyNettyExceptionHandler nettyExceptionHandler;

    @Autowired
    NettySsl nettySsl;

    /**
     * 心跳超时时间
     */
    // 读超时
    private static final int READ_IDEL_TIME_OUT = 10;
    // 写超时
    private static final int WRITE_IDEL_TIME_OUT = 15;
    // 所有超时
    private static final int ALL_IDEL_TIME_OUT = 20;



    @Override
    protected void initChannel(Channel ch) throws Exception {


        logger.info("收到新连接");
        // 获得 Channel 对应的 ChannelPipeline
        ChannelPipeline channelPipeline = ch.pipeline();
        // 添加一堆 NettyServerHandler 到 ChannelPipeline 中
        channelPipeline
                //证书
                .addLast("sslHandler", new SslHandler(nettySsl.getSslEngine()))
                // 空闲检测
                .addLast(new IdleStateHandler(READ_IDEL_TIME_OUT,WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.MINUTES))
                //websocket协议本身是基于http协议的，所以这边也要使用http解编码器
                .addLast(new HttpServerCodec())
                //以块的方式来写的处理器，防止发送大文件时导致内存溢出， channel.write(new ChunkedFile(new File("bigFile.mkv")))
                .addLast(new ChunkedWriteHandler())
                // 将HttpMessage和HttpContents聚合到一个完成的 FullHttpRequest或FullHttpResponse中,具体是FullHttpRequest对象还是FullHttpResponse对象取决于是请求还是响应
                // 需要放到HttpServerCodec这个处理器后面
                .addLast(new HttpObjectAggregator(8192))
                // 自定义的基础编码解码器
                /**
                 * netty websocket 处理
                 */
                // webSocket 数据压缩扩展，当添加这个的时候WebSocketServerProtocolHandler的第三个参数需要设置成true
                .addLast(new WebSocketServerCompressionHandler())
                // Websocket协议配置， 设置访问路径
                .addLast(new WebSocketServerProtocolHandler("/ws", "WebSocket", true, 65536 * 10))
                    /**
                     * websocket 文本 String
                     */
                //自定义处理器 JSON 文本
                .addLast(myWebSocketHandler)
                    /**
                     * websocket 二进制 binary
                     */
                //自定义处理器 二进制
                .addLast(myBinaryWebSocketFrameHandler)
                //全局异常捕获
                .addLast(nettyExceptionHandler);

    }

}